package cn.jasonone.tio.tcp.listener;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.tio.core.ChannelContext;
import org.tio.core.TioConfig;
import org.tio.core.intf.Packet;
import org.tio.core.stat.IpStat;
import org.tio.core.stat.IpStatListener;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @author xujie
 * @version 1.0
 * @date 2022/1/19 11:50
 */
@Slf4j
@Data
public class GlobalIpStatListener implements IpStatListener, ApplicationContextAware, InitializingBean {
    private static final Marker MARKER = MarkerFactory.getMarker("IpStatListener");

    private final Set<IpStatListener> ipStatListenerCache = new HashSet<>();

    private ApplicationContext applicationContext;
    @Override
    public void onExpired(TioConfig tioConfig, IpStat ipStat) {
        for (IpStatListener listener : ipStatListenerCache) {
            try {
                listener.onExpired(tioConfig, ipStat);
            } catch (Exception e) {
                log.error(MARKER, "监听器处理失败", e);
            }
        }
    }

    @Override
    public void onAfterConnected(ChannelContext channelContext, boolean isConnected, boolean isReconnect, IpStat ipStat) throws Exception {
        for (IpStatListener listener : ipStatListenerCache) {
            try {
                listener.onAfterConnected(channelContext, isConnected, isReconnect, ipStat);
            } catch (Exception e) {
                log.error(MARKER, "监听器处理失败", e);
            }
        }
    }

    @Override
    public void onDecodeError(ChannelContext channelContext, IpStat ipStat) {
        for (IpStatListener listener : ipStatListenerCache) {
            try {
                listener.onDecodeError(channelContext, ipStat);
            } catch (Exception e) {
                log.error(MARKER, "监听器处理失败", e);
            }
        }
    }

    @Override
    public void onAfterSent(ChannelContext channelContext, Packet packet, boolean isSentSuccess, IpStat ipStat) throws Exception {
        for (IpStatListener listener : ipStatListenerCache) {
            try {
                listener.onAfterSent(channelContext, packet, isSentSuccess, ipStat);
            } catch (Exception e) {
                log.error(MARKER, "监听器处理失败", e);
            }
        }
    }

    @Override
    public void onAfterDecoded(ChannelContext channelContext, Packet packet, int packetSize, IpStat ipStat) throws Exception {
        for (IpStatListener listener : ipStatListenerCache) {
            try {
                listener.onAfterDecoded(channelContext, packet, packetSize, ipStat);
            } catch (Exception e) {
                log.error(MARKER, "监听器处理失败", e);
            }
        }
    }

    @Override
    public void onAfterReceivedBytes(ChannelContext channelContext, int receivedBytes, IpStat ipStat) throws Exception {
        for (IpStatListener listener : ipStatListenerCache) {
            try {
                listener.onAfterReceivedBytes(channelContext, receivedBytes, ipStat);
            } catch (Exception e) {
                log.error(MARKER, "监听器处理失败", e);
            }
        }
    }

    @Override
    public void onAfterHandled(ChannelContext channelContext, Packet packet, IpStat ipStat, long cost) throws Exception {
        for (IpStatListener listener : ipStatListenerCache) {
            try {
                listener.onAfterHandled(channelContext, packet, ipStat, cost);
            } catch (Exception e) {
                log.error(MARKER, "监听器处理失败", e);
            }
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Map<String, IpStatListener> ipStatListenerMap = applicationContext.getBeansOfType(IpStatListener.class);
        for (IpStatListener statListener : ipStatListenerMap.values()) {
            if(!(statListener instanceof GlobalIpStatListener) && this.ipStatListenerCache.add(statListener)){
                log.debug(MARKER, "注册[IpStatListener]监听器:{}", statListener);
            }
        }
    }
}
